library Mount requires ListModule, Practicals, utils

    struct MountUnitType extends array
        delegate UnitType m_unitType

        string m_attachPoint

        static method get takes integer unitId returns thistype
            return UnitType.get(unitId)
        endmethod

        static method create takes integer unitId returns thistype
            local thistype this = thistype.get(unitId)
            if this > 0 then
                return this
            endif

            // 默认 chest
            set this.m_attachPoint = "chest"

            return this
        endmethod

    endstruct

    struct Mount

        unit m_mount
        unit m_owner

        MountUnitType m_mountUnitType

        private effect m_model

        implement StructList

        static method get takes unit u returns thistype
            local thistype d = thistype.first
            loop
                exitwhen (d <= 0)
                if d.m_mount == u then
                    return d
                endif
                set d = d.next
            endloop
            return 0
        endmethod

        static method getByOwner takes unit u returns thistype
            local thistype d = thistype.first
            loop
                exitwhen (d <= 0)
                if d.m_owner == u then
                    return d
                endif
                set d = d.next
            endloop
            return 0
        endmethod

        static method create takes unit owner returns thistype
            local thistype this = thistype.get(owner)
            if this > 0 then
                return this
            endif

            set this = thistype.allocate()
            set this.m_owner = owner

            call this.listAdd()
            return this
        endmethod

        method destroy takes nothing returns nothing
            if this.m_model != null then
                call DestroyEffect(this.m_model)
            endif
            if this.m_mount != null then
                call RemoveUnit(this.m_mount)
            endif
            
            set this.m_model = null
            set this.m_mount = null
            set this.m_owner = null
            
            call this.listRemove()
            call this.deallocate()
        endmethod

        method setMountUnitType takes MountUnitType unitType returns nothing
            set this.m_mountUnitType = unitType
        endmethod

        method summonMount takes nothing returns nothing
            local real x
            local real y
            local real facing
            local Unit oud

            if this.m_mountUnitType <= 0 then
                return
            endif

            set x = GetUnitX(this.m_owner)
            set y = GetUnitY(this.m_owner)
            set facing = GetUnitFacing(this.m_owner)
            set oud = Unit.get(this.m_owner)

            set this.m_mount = CreateUnit(GetOwningPlayer(this.m_owner), this.m_mountUnitType.m_unitId, x, y, facing)
            call SetUnitScale(this.m_mount, oud.m_modelScale, oud.m_modelScale, oud.m_modelScale)
            call AddEffectTarget("Abilities\\Spells\\Human\\Polymorph\\PolyMorphDoneGround.mdl", this.m_mount, "origin")

            set this.m_model = AddSpecialEffectTarget(oud.m_model, this.m_mount, this.m_mountUnitType.m_attachPoint)

            call RefreshUnitEffectColor()
            call SelectUnitForPlayerSingle(this.m_mount, GetOwningPlayer(this.m_owner))
            call ForceUICancelBJ(GetOwningPlayer(this.m_owner))
            call ShowUnit(this.m_owner, false)
        endmethod

    endstruct

endlibrary
